by Bill Heyman
In This Chapter
Beyond ODBC and ADO, the next step in the evolution of data access requires that the focus be less on databases and more on general datasources. At the same time, the general software development approach requires the packaging of reusable software parts in components. The convergence of these requirements resulted in the development of Microsofts strategic software direction, called Universal Data Access (UDA).
A key component of UDA is OLE DB. Based on COM, OLE DB defines a set of interfaces for interacting with general datasources from both the client (consumer) side and the server (provider) side. In addition, Microsoft created a language-independent, higher-level data consumer interface called ActiveX Data Objects (ADO), which is built upon the OLE DB infrastructure. This chapter discusses these new interfaces for data access for Windows-based applications: OLE DB and ADO.
OLE DB is a datasource-independent, COM-based interface for providing and consuming data. It is generic enough to support any datasource that can provide tabular data, yet still powerful enough to enable specific interaction with each datasource to enable it to perform at its optimum.
In the standard client/server world, there are sources of data (commonly called servers) and there are users of data (commonly called clients). In OLE DB, these are called providers and consumers, respectively.
This chapter discusses the development of OLE DB consumers using the ATL template interface provided by Microsoft Visual C++. Please refer to the OLE DB documentation from Microsoft for more information on the creation of OLE DB providers.
By itself, OLE DB is extremely powerful and very general purpose. However, its interface is not always the easiest way of interacting with datasources in a straightforward, standard manner. Furthermore, OLE DB is not well suited for interfacing to Visual Basic, Java, and other languages.
To meet the requirements for everyday datasource development and to be a logical extension of MFC/ODBC and DAO, Microsoft created ActiveX Data Objects (ADO). ADO is implemented using OLE DB provider interfaces. However, its interface allows programmers to interact with data at a higher level than OLE DB provides.
Certainly, you can use both OLE DB and ADO from Visual C++ code. In fact, because both are COM-based components, there is a variety of mechanisms for interfacing them, from using #import to using the Microsoft-defined C++ interfaces.
If you are looking for a high-performance and more functional interface, select OLE DB. The ATL class wrappers for OLE DB enhance and extend its base functionality, without sacrificing its performance.
If you are looking for a set of high-level objects that can easily be used from a variety of languages and retains some of the look-and-feel of MFC/ODBC and DAO, select ADO.
Although you can access the OLE DB COM objects directly, there is an Active Template Library (ATL) set of classes that encapsulate the COM objects for you. This makes using OLE DB much easier from the C++ environment. To use the ATL OLE DB consumer classes, you must add the following file inclusion line to your program, usually in the stdafx.h file in your project:
#include <atldbcli.h>
Visual Studio provides an ATL Object Wizard that can greatly assist you in creating programs that act as OLE DB consumers. The following steps demonstrate how to generate classes for the Books table in the TechBooks sample database. To add this support to your application, follow these steps:
Figure 19.1 The ATL Object Wizard dialog.
Figure 19.2 The ATL Object Wizard Properties dialog.
Figure 19.3 The Data Link Properties dialogs Provider tab.
Figure 19.4 The Data Link Properties dialogs Connection tab.
Figure 19.5 The Select Database Table dialog.
Figure 19.6 The ATL Object Wizard Properties dialog with class information.
Listing 19.1 The Generated CBooksAccessor Class
class CBooksAccessor
{
public:
LONG m_BookId;
LONG m_CategoryId;
TCHAR m_ISBN[13];
DATE m_PublicationDate;
LONG m_PublisherId;
CURRENCY m_RetailPrice;
TCHAR m_Title[251];
LONG m_TopicId;
BEGIN_COLUMN_MAP(CBooksAccessor)
COLUMN_ENTRY(1, m_BookId)
COLUMN_ENTRY(2, m_Title)
COLUMN_ENTRY(3, m_PublisherId)
COLUMN_ENTRY_TYPE(4, DBTYPE_DATE, m_PublicationDate)
COLUMN_ENTRY(5, m_ISBN)
COLUMN_ENTRY_TYPE(6, DBTYPE_CY, m_RetailPrice)
COLUMN_ENTRY(7, m_CategoryId)
COLUMN_ENTRY(8, m_TopicId)
END_COLUMN_MAP()
// You may wish to call this function if you are inserting a
// record and wish to initialize all the fields, if you are
// not going to explicitly set all of them.
void ClearRecord()
{
memset(this, 0, sizeof(*this));
}
};